//
// Created by Administrator on 2019/10/28.
//

#include "ExtrAudioModule.h"

void printError(int error_code, char *error_str) {
    av_strerror(error_code, error_str, 1024);
    LOGD(error_str);

}

void adts_header(char *szAdtsHeader, int dataLen) {

    int audio_object_type = 2;
    int sampling_frequency_index = 7;
    int channel_config = 2;

    int adtsLen = dataLen + 7;

    szAdtsHeader[0] = 0xff;         //syncword:0xfff                          高8bits
    szAdtsHeader[1] = 0xf0;         //syncword:0xfff                          低4bits
    szAdtsHeader[1] |= (0 << 3);    //MPEG Version:0 for MPEG-4,1 for MPEG-2  1bit
    szAdtsHeader[1] |= (0 << 1);    //Layer:0                                 2bits
    szAdtsHeader[1] |= 1;           //protection absent:1                     1bit

    szAdtsHeader[2] = (audio_object_type - 1)
            << 6;            //profile:audio_object_type - 1                      2bits
    szAdtsHeader[2] |= (sampling_frequency_index & 0x0f)
            << 2; //sampling frequency index:sampling_frequency_index  4bits
    szAdtsHeader[2] |= (0
            << 1);                             //private bit:0                                      1bit
    szAdtsHeader[2] |= (channel_config & 0x04)
            >> 2;           //channel configuration:channel_config               高1bit

    szAdtsHeader[3] =
            (channel_config & 0x03) << 6;     //channel configuration:channel_config      低2bits
    szAdtsHeader[3] |= (0
            << 5);                      //original：0                               1bit
    szAdtsHeader[3] |= (0
            << 4);                      //home：0                                   1bit
    szAdtsHeader[3] |= (0
            << 3);                      //copyright id bit：0                       1bit
    szAdtsHeader[3] |= (0
            << 2);                      //copyright id start：0                     1bit
    szAdtsHeader[3] |= ((adtsLen & 0x1800) >> 11);           //frame length：value   高2bits

    szAdtsHeader[4] = (uint8_t) ((adtsLen & 0x7f8) >> 3);     //frame length:value    中间8bits
    szAdtsHeader[5] = (uint8_t) ((adtsLen & 0x7) << 5);       //frame length:value    低3bits
    szAdtsHeader[5] |= 0x1f;                                 //buffer fullness:0x7ff 高5bits
    szAdtsHeader[6] = 0xfc;
}


void ExtrAudio::_extrAudio(const char *_path, const char *_targPath) {

    LOGD(_path);
    LOGD(_targPath);

    int err_code = 0;
    char errors[1024];
    FILE *dst_fd = NULL;
    int audio_stream_index = -1;
    int len;
    AVFormatContext *oAvFormatContext = NULL;
    AVOutputFormat *avOutputFormat = NULL;

    AVStream *out_stream = NULL;
    AVFormatContext *fAvFormatContext = NULL;

    AVFrame *frame = NULL;
    AVPacket pkt;


    //1.注册所有解码器
    av_register_all();

    //2.创建文件
    dst_fd = fopen(_targPath, "wb");

    if (!dst_fd) {
        LOGD("error fopen");
    }

    //3.打开媒体文件
    err_code = avformat_open_input(&fAvFormatContext, _path, NULL, NULL);
    if (err_code < 0) {
        printError(err_code, errors);
        return;
    }

    //3.打开媒体文件
    /*  1.查找解码器：find_decoder()
      2.打开解码器：avcodec_open2()
      3.读取完整的一帧压缩编码的数据：read_frame_internal()
      注：av_read_frame()内部实际上就是调用的read_frame_internal()。
      4.解码一些压缩编码数据：try_decode_frame()
      原文链接：https://blog.csdn.net/leixiaohua1020/article/details/44084321*/
    err_code = avformat_find_stream_info(fAvFormatContext, NULL);

    if (err_code < 0) {
        printError(err_code, errors);
        return;
    }

    frame = av_frame_alloc();

    if (!frame) {
        LOGD("无法分配帧内存");
        return;
    }



    /*a. 就是要获取音视频及字幕的流索引stream_index
    b.以前没有函数av_find_best_stream时，获取索引可以通过如下*/
    audio_stream_index = av_find_best_stream(fAvFormatContext, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
    if (audio_stream_index < 0) {
        LOGD("无法获取获取媒体文件流信息");
        return;
    }


    av_init_packet(&pkt);
    pkt.data = NULL;
    pkt.size = 0;
    //读取帧中数据包
    while (av_read_frame(fAvFormatContext, &pkt) >= 0) {

        if (pkt.stream_index == audio_stream_index) {
            char adts_header_buf[7];
            adts_header(adts_header_buf, pkt.size);
            fwrite(adts_header_buf, 1, 7, dst_fd);
            len = fwrite(pkt.data, 1, pkt.size, dst_fd);
            if (len != pkt.size) {
                LOGD("is not equal");
            }

        }
        av_packet_unref(&pkt);
    }

    /*close input media file*/
    avformat_close_input(&fAvFormatContext);
    if (dst_fd) {
        fclose(dst_fd);
    }


}



